package net.sf.calibur.transport.message;

import java.io.InputStream;
import java.io.OutputStream;

import net.sf.calibur.msgbuf.CommandFactory;

public abstract class Message {
	public final static int MT_APPLICATION = 0;
	public final static int MT_APPLICATION_ACK = 9;
	
	public final static int MT_REQUEST_SESSION = 1;
	public final static int MT_SESSION_ESTABLISHED = 2;
	
	public final static int MT_SERVER_HEARTBEAT = 3;
	public final static int MT_SERVER_HEARTBEAT_ACK = 4;
	
	public final static int MT_CLIENT_HEARTBEAT = 5;
	public final static int MT_CLIENT_HEARTBEAT_ACK = 6;
	
	public static Message createMessage(int type, CommandFactory factory) {
		return createMessage(type, null, factory);
	}
	
	public static Message createMessage(int type, MessageHead head, CommandFactory factory) {
		switch (type) {
		case Message.MT_APPLICATION:
			return new CommandMessage(head, factory);
		case Message.MT_APPLICATION_ACK:
			return new CommandAckMessage();

		case Message.MT_REQUEST_SESSION:
			return new RequestSessionMessage();

		case Message.MT_SESSION_ESTABLISHED:
			return new SessionEstablishedMessage();

		case Message.MT_CLIENT_HEARTBEAT:
		case Message.MT_CLIENT_HEARTBEAT_ACK:
		case Message.MT_SERVER_HEARTBEAT:
		case Message.MT_SERVER_HEARTBEAT_ACK:
			return new HeartBeatMessage(type);

		default:
			throw new IllegalArgumentException("Unknown message type " + type);
		}
	}
	
	/** 消息类型，0代表应用报文（MessageBean）；非0值代表管理指令 */
	private int type;
	/** 顺序号 */
	private int sequence;
	/** 创建（到达）时间戳 */
	private long arrivedTimestamp;
	/** 报文头信息 */
	private MessageHead head;
	
	public Message(int type) {
		this.arrivedTimestamp = System.currentTimeMillis();
		this.type = type;
	}
	
	public int getSequence() {
		return sequence;
	}
	
	public void setSequence(int sequ) {
		this.sequence = sequ;
	}

	public long getArrivedTimestamp() {
		return arrivedTimestamp;
	}

	public int getType() {
		return type;
	}
	
	public void release() {
	}
	

	public MessageHead getHead() {
		return head;
	}
	
	abstract public void serialize(OutputStream output) throws Exception;
	abstract public void deserialize(InputStream input) throws Exception;
}
